package sim32;

/**
 * @author Piotr
 * Class representing the MEMStage. The actual data memory has been moved into the Pipeline
 * class to allow for multiple of these stages in parallel.
 */
public class MEMStage extends PipeStage {
	
	
	/**
	 * Creates a new MEMStage.
	 */
	MEMStage(int pipeID) {
		super(pipeID);
	}
	
	@Override
	int cycle(PipeStage prevStage) throws InvalidInstructionException {
		instr = prevStage.passInstruction();
		if (instr == null) {
			return 0;
		} else {
			if (instr.isNop()) {
				return 0;
			} else {
				instr.cycle();
				switch (instr.iType) {
				case LOAD:
					doLoad(instr);
					break;
				case STORE:
					doStore(instr);
					break;
				default:
					break;
				}
			}
		}
		return 1;
	}
	
	private void doStore(Instruction instr) {
		if (!instr.arg1Ready) {
			// Forward value
			Integer val = Sim.pipe.hzc.tryForwarding(instr.arg1Reg, this.getClass(), pipeID);
			if (val == null) {
				System.out.println("Stall needed in MEM stage. Should not happen.");
				System.exit(1);
			} else {
				instr.arg1Val = val;
				instr.arg1Ready = true;
			}
		}
		Sim.pipe.writeDM(instr.memAddr, instr.arg1Val); //memAddr is calculated in EX		
	}

	private void doLoad(Instruction instr) {
		instr.setDest1Val(Sim.pipe.readDM(instr.memAddr)); //memAddr is calculated in EX
	}

}
